package de.suur.jarmi.gson;

import java.io.Serializable;
import java.lang.reflect.Type;

import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonDeserializer;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParseException;
import com.google.gson.JsonPrimitive;
import com.google.gson.JsonSerializationContext;
import com.google.gson.JsonSerializer;

import de.suur.jarmi.common.JarmiException;
import de.suur.jarmi.common.Response;

public class ResponseAdapter implements JsonSerializer<Response>,
		JsonDeserializer<Response> {

	private static final String EXCEPTION = "exception";
	private static final String RESULT = "result";
	private static final String RESULT_CLASS = "resultClass";
	private static final String SUCCESS = "success";

	@Override
	public Response deserialize(JsonElement json, Type typeOfT,
			JsonDeserializationContext context) throws JsonParseException {
		JsonObject jsonObject = json.getAsJsonObject();

		boolean success = jsonObject.get(SUCCESS).getAsBoolean();

		if (success) {
			try {
				JsonElement resultClassElement = jsonObject.get(RESULT_CLASS);
				if (resultClassElement != null) {
					Class<?> resultClass = Class.forName(resultClassElement
							.getAsString());
					Serializable result = context.deserialize(
							jsonObject.get(RESULT), resultClass);
					return new Response(result);
				} else {
					return new Response((Serializable) null);
				}
			} catch (ClassNotFoundException e) {
				e.printStackTrace();
			}
			return null;
		} else {
			JarmiException exception = context.deserialize(
					jsonObject.get(EXCEPTION), JarmiException.class);
			return new Response(exception);
		}

	}

	@Override
	public JsonElement serialize(Response src, Type typeOfSrc,
			JsonSerializationContext context) {
		JsonObject jsonObject = new JsonObject();

		if (src.isSuccess()) {
			jsonObject.add(RESULT, context.serialize(src.getResult()));
			if (src.getResult() != null) {
				jsonObject.add(RESULT_CLASS, new JsonPrimitive(src.getResult()
						.getClass().getName()));
			}
		} else {
			jsonObject.add(EXCEPTION, context.serialize(src.getException()));
		}

		jsonObject.add(SUCCESS, new JsonPrimitive(src.isSuccess()));

		return jsonObject;
	}

}
